import type { Component } from 'types/component'
import type { ComponentOptions } from 'types/options'
import type { VNodeComponentOptions, VNodeData } from 'types/vnode'

/**
 * @internal
 */
// 定义一个名为VNode的类，代表Vue的虚拟节点
export default class VNode {
  tag?: string  // 可选的标签名
  data: VNodeData | undefined // 节点的数据对象，包含属性、指令等
  children?: Array<VNode> | null // 子节点数组，可以是VNode实例或null
  text?: string // 文本内容，如果节点是文本节点，则存储文本内容
  elm: Node | undefined // 对应的DOM元素
  ns?: string // 命名空间，用于SVG元素
  context?: Component // 渲染该节点的组件实例
  key: string | number | undefined // 节点的key，用于追踪节点身份
  componentOptions?: VNodeComponentOptions // 组件选项，如果是组件节点，则包含组件的配置信息
  componentInstance?: Component  // 组件实例，如果是组件节点，则存储组件实例
  parent: VNode | undefined | null // 父节点，用于组件占位符节点

  // strictly internal
  // 以下是内部使用的属性
  raw: boolean // 是否包含原始HTML（仅服务端）
  isStatic: boolean // 是否是静态节点（提升）
  isRootInsert: boolean // 是否是根插入点（用于进入过渡检查）
  isComment: boolean // 是否是空注释占位符
  isCloned: boolean // 是否是克隆节点
  isOnce: boolean // 是否是v-once节点
  asyncFactory?: Function // 异步组件工厂函数
  asyncMeta: Object | void // 异步组件元数据
  isAsyncPlaceholder: boolean // 是否是异步占位符
  ssrContext?: Object | void // 服务端渲染上下文
  fnContext: Component | void // 函数式节点的真实上下文vm
  fnOptions?: ComponentOptions | null // 用于SSR缓存
  devtoolsMeta?: Object | null // 用于存储函数式渲染上下文以供devtools使用
  fnScopeId?: string | null // 函数式作用域ID支持
  isComponentRootElement?: boolean | null // 用于SSR指令的组件根元素标识
// 构造函数，初始化VNode实例
  constructor(
    tag?: string,
    data?: VNodeData,
    children?: Array<VNode> | null,
    text?: string,
    elm?: Node,
    context?: Component,
    componentOptions?: VNodeComponentOptions,
    asyncFactory?: Function
  ) {
    // 初始化VNode的属性
    this.tag = tag
    this.data = data
    this.children = children
    this.text = text
    this.elm = elm
    this.ns = undefined
    this.context = context
    this.fnContext = undefined
    this.fnOptions = undefined
    this.fnScopeId = undefined
    this.key = data && data.key
    this.componentOptions = componentOptions
    this.componentInstance = undefined
    this.parent = undefined
     // 初始化内部属性
    this.raw = false
    this.isStatic = false
    this.isRootInsert = true
    this.isComment = false
    this.isCloned = false
    this.isOnce = false
    this.asyncFactory = asyncFactory
    this.asyncMeta = undefined
    this.isAsyncPlaceholder = false
  }

  // DEPRECATED: alias for componentInstance for backwards compat.
  // 已弃用：为了向后兼容，提供componentInstance的别名
  /* istanbul ignore next */
  get child(): Component | void {
    return this.componentInstance
  }
}
// 创建一个空的VNode，通常用作占位符
export const createEmptyVNode = (text: string = '') => {
  const node = new VNode()
  node.text = text
  node.isComment = true
  return node
}
//创建一个文本VNode
export function createTextVNode(val: string | number) {
  return new VNode(undefined, undefined, undefined, String(val))
}

// optimized shallow clone
// used for static nodes and slot nodes because they may be reused across
// multiple renders, cloning them avoids errors when DOM manipulations rely
// on their elm reference.
/**
 * 优化了用于静态节点和槽节点的浅克隆，因为它们可能在多个渲染中被重用，
 * 克隆它们可以避免DOM操作依赖于它们的elm引用时的错误。
 * @param vnode 
 * @returns 
 */
export function cloneVNode(vnode: VNode): VNode {
  const cloned = new VNode(
    vnode.tag,
    vnode.data,
    // #7975
    // clone children array to avoid mutating original in case of cloning
    // a child.
    // 克隆子节点数组，避免在克隆子节点时修改原始数组
    vnode.children && vnode.children.slice(),
    vnode.text,
    vnode.elm,
    vnode.context,
    vnode.componentOptions,
    vnode.asyncFactory
  )
  // 复制其他属性
  cloned.ns = vnode.ns
  cloned.isStatic = vnode.isStatic
  cloned.key = vnode.key
  cloned.isComment = vnode.isComment
  cloned.fnContext = vnode.fnContext
  cloned.fnOptions = vnode.fnOptions
  cloned.fnScopeId = vnode.fnScopeId
  cloned.asyncMeta = vnode.asyncMeta
  cloned.isCloned = true
  return cloned
}
